/*-------------------------------------------------------------------------
 * CLR版本:     4.0.30319.42000
 * 创建人:      song
 * 创建时间：   2024/4/9 17:56:20
 * 功 能：      基础渲染设置模块
 *-------------------------------------------------------------------------*/

#if UNITY_EDITOR
namespace SCore.Editor.SShaderDraw
{
    using System;
    using System.Collections.Generic;
    using UnityEditor;
    using UnityEngine;

    public class SRenderProGUI : SComponentGUIBase
    {
        private enum ZwriteMode //深度写入
        {
            Off,
            On
        }

        private enum BlendMode
        {
            Additive,
            AlphaBlend,
            Custom
        }

        static bool foldout = true;

        static bool stencil = true;

        int _Blend;
        SEnumProp _Zwrite, _SrcBlend, _DstBlend, _Cull, _StencilComp, _StencilOp;
        SRangeProp _Stencil, _StencilRendMask, _StencilWriteMask;

        public SRenderProGUI(MaterialEditor materialEditor, Dictionary<string, MaterialProperty> dics) : base(
            materialEditor, dics)
        {
            _Zwrite = new SEnumProp("_Zwrite", Styles.Zwrite, materialEditor, dics, (int)ZwriteMode.On,
                Enum.GetNames(typeof(ZwriteMode)));
            _Cull = new SEnumProp("_Cull", Styles.Cull, materialEditor, dics, (int)UnityEngine.Rendering.CullMode.Back,
                Enum.GetNames(typeof(UnityEngine.Rendering.CullMode)));
            _SrcBlend = new SEnumProp("_SrcBlend", Styles.SrcBlend, materialEditor, dics,
                (int)UnityEngine.Rendering.BlendMode.One, Enum.GetNames(typeof(UnityEngine.Rendering.BlendMode)));
            _DstBlend = new SEnumProp("_DstBlend", Styles.DstBlend, materialEditor, dics,
                (int)UnityEngine.Rendering.BlendMode.Zero, Enum.GetNames(typeof(UnityEngine.Rendering.BlendMode)));
            _Blend = (int)BlendMode.Additive;

            _Stencil = new SRangeProp("_Stencil", Styles.Stencil, materialEditor, dics, 0f, 0f, 255f);
            _StencilComp = new SEnumProp("_StencilComp", Styles.StencilComp, materialEditor, dics,
                (int)UnityEngine.Rendering.CompareFunction.Always,
                Enum.GetNames(typeof(UnityEngine.Rendering.CompareFunction)));
            _StencilOp = new SEnumProp("_StencilOp", Styles.StencilOp, materialEditor, dics,
                (int)UnityEngine.Rendering.StencilOp.Keep, Enum.GetNames(typeof(UnityEngine.Rendering.StencilOp)));
            _StencilRendMask = new SRangeProp("_StencilRendMask", Styles.StencilRendMask, materialEditor, dics, 255f,
                0f, 255f);
            _StencilWriteMask = new SRangeProp("_StencilWriteMask", Styles.StencilWriteMask, materialEditor, dics, 255f,
                0f, 255f);
        }

        public override void Changed()
        {
        }

        public override void DrawProperties()
        {
            GUILayout.BeginVertical("box");
            SPropBase[] ps = new SPropBase[] { _Zwrite, _Cull };
            base.DrawPartTitle(Styles.RenderModule, ref foldout, () =>
            {
                foreach (var p in base.lProps)
                {
                    p.Reset();
                }
            }, 0f);

            if (foldout)
            {
                foreach (var prop in ps)
                {
                    prop.Draw(15f);
                }

                DrawBlend(15f);
                DrawStencil(30f);
            }

            GUILayout.EndVertical();
        }

        public override void RefreshProperties()
        {
            this.lProps.Clear();
            this.lProps.Add(_Zwrite);
            this.lProps.Add(_Cull);
            this.lProps.Add(_SrcBlend);
            this.lProps.Add(_DstBlend);

            this.lProps.Add(_Stencil);
            this.lProps.Add(_StencilComp);
            this.lProps.Add(_StencilOp);
            this.lProps.Add(_StencilRendMask);
            this.lProps.Add(_StencilWriteMask);
        }

        #region stencil

        private void DrawStencil(float space)
        {
            SPropBase[] ps = new SPropBase[]
                { _Stencil, _StencilComp, _StencilOp, _StencilRendMask, _StencilWriteMask };
            base.DrawPartTitle(Styles.StencilModule, ref stencil, () =>
            {
                foreach (var p in ps)
                {
                    p.Reset();
                }
            }, 15f);
            if (stencil)
            {
                foreach (var prop in ps)
                {
                    prop.Draw(space);
                }
            }
        }

        #endregion

        #region Blend

        private void GetBlendMode()
        {
            if ((((int)this._SrcBlend.Value) == 5) && (((int)this._DstBlend.Value) == 1))
            {
                this._Blend = (int)BlendMode.Additive;
            }
            else if ((((int)this._SrcBlend.Value) == 5) && (((int)this._DstBlend.Value) == 10))
            {
                this._Blend = (int)BlendMode.AlphaBlend;
            }
            else
            {
                this._Blend = (int)BlendMode.Custom;
            }
        }

        private void SetBlendMode()
        {
            if (this._Blend == (int)BlendMode.Additive)
            {
                this._SrcBlend.Value = 5;
                this._DstBlend.Value = 1;
            }
            else if (this._Blend == (int)BlendMode.AlphaBlend)
            {
                this._SrcBlend.Value = 5;
                this._DstBlend.Value = 10;
            }
            else
            {
                this._SrcBlend.Value = 1;
                this._DstBlend.Value = 0;
            }
        }

        private void DrawBlendMode(float space)
        {
            GUILayout.BeginHorizontal();
            GUILayout.Space(space);
            EditorGUILayout.LabelField(Styles.BlendMode, SPropBase.fontStyle);
            this._Blend = EditorGUILayout.Popup(this._Blend, Enum.GetNames(typeof(BlendMode)));
            SetBlendMode();
            GUI.color = SPropBase.ResetBtnColor;
            GUILayoutOption[] options = new GUILayoutOption[] { GUILayout.Width(40) };
            if (GUILayout.Button("重置", options))
            {
                this._Blend = EditorGUILayout.Popup((int)BlendMode.Additive, Enum.GetNames(typeof(BlendMode)));
                SetBlendMode();
            }

            GUI.color = Color.white;
            GUILayout.EndHorizontal();
        }

        private void DrawCustomBlendMode(float space)
        {
            GUILayout.BeginHorizontal();
            GUILayout.Space(space);
            EditorGUILayout.LabelField(Styles.BlendMode, SPropBase.fontStyle);
            this._Blend = EditorGUILayout.Popup(this._Blend, Enum.GetNames(typeof(BlendMode)));
            if (this._Blend != (int)BlendMode.Custom)
            {
                SetBlendMode();
            }

            GUI.color = SPropBase.ResetBtnColor;
            GUILayoutOption[] options = new GUILayoutOption[] { GUILayout.Width(40) };
            if (GUILayout.Button("重置", options))
            {
                this._Blend = EditorGUILayout.Popup((int)BlendMode.Additive, Enum.GetNames(typeof(BlendMode)));
                SetBlendMode();
            }

            GUI.color = Color.white;
            GUILayout.EndHorizontal();
        }

        private void DrawBlend(float space)
        {
            if (_SrcBlend.Exist && _DstBlend.Exist)
            {
                GetBlendMode();
                if (this._Blend == (int)BlendMode.Custom)
                {
                    DrawCustomBlendMode(space);
                    _SrcBlend.Draw(space + space);
                    _DstBlend.Draw(space + space);
                }
                else
                {
                    DrawBlendMode(space);
                }
            }
        }

        #endregion

        private class Styles
        {
            public static GUIContent RenderModule = new GUIContent("基础渲染", "基础渲染模模块");
            public static GUIContent Zwrite = new GUIContent("深度写入", "深度写入是否开启");
            public static GUIContent SrcBlend = new GUIContent("源", "源Blend值");
            public static GUIContent DstBlend = new GUIContent("目标", "目标Blend值");
            public static GUIContent BlendMode = new GUIContent("混合模式", "混合模式选择");
            public static GUIContent Cull = new GUIContent("面剔除", "面剔除");


            public static GUIContent StencilModule = new GUIContent("模板测试", "模板测试模块");
            public static GUIContent Stencil = new GUIContent("模板值", "模板值");
            public static GUIContent StencilComp = new GUIContent("模板比较方式", "模板比较方式");
            public static GUIContent StencilOp = new GUIContent("模板通过操作", "模板通过操作");
            public static GUIContent StencilRendMask = new GUIContent("读取掩码", "读取掩码");
            public static GUIContent StencilWriteMask = new GUIContent("写入掩码", "写入掩码");
        }
    }
}
#endif